Skip to content

feat(docs): expand ComponentGrid in llms.txt output#1509

Open
SeieunYoo wants to merge 7 commits intodevfrom
joy-yoo_karrot/llms-docs-fix
Open

feat(docs): expand ComponentGrid in llms.txt output#1509
SeieunYoo wants to merge 7 commits intodevfrom
joy-yoo_karrot/llms-docs-fix

Conversation

@SeieunYoo
Copy link
Copy Markdown
Contributor

@SeieunYoo SeieunYoo commented Apr 22, 2026

Add a rule that transforms into a categorized markdown list of components so /llms/docs/components.txt exposes the full component index instead of a bare MDX tag.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • ComponentGrid 요소가 카테고리별 섹션을 자동 생성하여 컴포넌트를 그룹화·알파벳 정렬하고 제목·설명·URL을 표시
    • 항목이 없거나 오류 발생 시 원본 노드를 유지(출력 안전성 향상)
    • deprecated 표기가 있는 항목은 목록에서 자동 제외
  • 테스트

    • ComponentGrid 출력(그룹화·정렬·필터링) 검증용 단위 테스트 추가
    • 비대상 노드 통과 처리 및 출력 일치성 검증 사례 추가

Add a rule that transforms <ComponentGrid /> into a categorized
markdown list of components so /llms/docs/components.txt exposes
the full component index instead of a bare MDX tag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 22, 2026

⚠️ No Changeset found

Latest commit: e371456

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

로컬 컴포넌트 MDX 문서를 스캔해 frontmatter로 엔트리를 수집·캐시하고, 카테고리별로 그룹화한 Markdown 링크 목록을 생성해 <ComponentGrid /> MDX 노드를 HTML 마크다운으로 대체하는 새 규칙과 관련 테스트·픽스처를 추가합니다.

Changes

Cohort / File(s) Summary
Rule implementation
docs/app/_llms/rules/component-grid-rule.ts
컴포넌트 디렉터리 탐색(여러 후보 경로), .mdx frontmatter 파싱(title/description/deprecated), ComponentEntry 정의·캐싱, 카테고리별 그룹화·정렬, buildMarkdown() 생성 및 ComponentGrid MDX 노드 변환(존재 시 html 노드로 대체).
Rule registration
docs/app/_llms/rules/index.ts
componentGridRule 임포트 및 named export 추가, activeRules 배열에 등록.
Fixtures (input/output)
docs/app/_llms/__fixtures__/component-grid/basic.output.md, docs/app/_llms/__fixtures__/component-grid/passthrough.input.mdx, docs/app/_llms/__fixtures__/component-grid/passthrough.output.mdx
컴포넌트 목록용 출력 MD 픽스처와 passthrough 입력/출력 픽스처 추가(예: <SomethingElse />).
Tests
docs/app/_llms/rules/component-grid-rule.test.ts
buildMarkdown 출력 비교 테스트, MDX passthrough 경로 테스트(normalizeLLMBodyWithRules 사용) 추가. Assertions는 픽스처와 normalizeForAssert로 비교. 테스트 전용 파일만 변경됨.

Sequence Diagram(s)

sequenceDiagram
    participant LLM as "LLM Processor"
    participant Rule as "ComponentGrid Rule"
    participant FS as "Filesystem (docs/components)"
    participant Cache as "In‑memory Cache"

    LLM->>Rule: encounters <ComponentGrid /> node
    Rule->>Cache: check cached entries
    alt cache miss
        Rule->>FS: scan category folders & read .mdx files
        FS-->>Rule: return file list & frontmatter
        Rule->>Rule: parse frontmatter, filter deprecated, build entries
        Rule->>Cache: store entries
    end
    Rule->>Rule: buildMarkdown(grouped entries)
    Rule-->>LLM: return HTML node with generated markdown
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 폴더를 훑어 링크를 엮었네,
frontmatter로 이름과 설명을 모았네.
오래된 건 건너뛰고 정렬해 놓고,
한 줄의 마크다운으로 길을 내었네.
토끼가 남긴 작은 목록, 행복한 발견 ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(docs): expand ComponentGrid in llms.txt output' accurately summarizes the main change: adding a rule to transform the ComponentGrid MDX tag into categorized markdown component listings for documentation generation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch joy-yoo_karrot/llms-docs-fix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/app/_llms/rules/component-grid-rule.test.ts`:
- Around line 5-30: The tests in component-grid-rule.test.ts use partial
matching (toContain/not.toContain) against normalizeLLMBodyWithRules output;
replace these with full-fixture comparisons using normalizeForAssert and
readFixture: import { normalizeForAssert, readFixture } from
'docs/app/_llms/test-utils.ts', call const expected =
readFixture('<appropriate-fixture-filename>.md') and assert
expect(normalizeForAssert(actual)).toBe(normalizeForAssert(expected)); update
each test ("expands ComponentGrid...", "excludes deprecated components...") to
use this pattern and corresponding fixtures, and rename the third test from
"leaves the node as-is when no components are available" to "non-target node
passthrough" (or similar) while also asserting full-fixture equality for the
passthrough case using normalizeForAssert. Ensure tests still call
normalizeLLMBodyWithRules(input, [componentGridRule]) as before.

In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 28-42: parseFrontmatter currently returns all frontmatter values
as strings so a frontmatter like deprecated: false becomes the string "false"
and is treated truthily; update parseFrontmatter to detect boolean-like values
(at least for the "deprecated" key) and convert "true"/"false"
(case-insensitive) to actual booleans (true/false) before storing in result, or
more generally parse "true"/"false" and numeric strings to proper types;
reference the parseFrontmatter function and the "deprecated" frontmatter key so
the boolean false is not treated as truthy in the downstream filter that
excludes deprecated components.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7cfa20d2-5930-43f0-ab0e-243cd406575d

📥 Commits

Reviewing files that changed from the base of the PR and between 20bca67 and 6ed8858.

📒 Files selected for processing (3)
  • docs/app/_llms/rules/component-grid-rule.test.ts
  • docs/app/_llms/rules/component-grid-rule.ts
  • docs/app/_llms/rules/index.ts

Comment thread docs/app/_llms/rules/component-grid-rule.test.ts
Comment thread docs/app/_llms/rules/component-grid-rule.ts Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 22, 2026

Alpha Preview (Docs)

- Treat deprecated: false / "no" / empty as not deprecated so valid
  components are no longer filtered out by the string-coerced parser.
- Switch tests to fixture-based equality via readFixture /
  normalizeForAssert to match the project's _llms test convention,
  and add unit coverage for isDeprecatedValue.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

Alpha Preview (Stackflow SPA)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

Alpha Preview (Storybook)

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
docs/app/_llms/rules/component-grid-rule.ts (4)

86-91: 모듈 수준 캐시는 프로세스 생애 동안 무효화되지 않습니다.

cachedEntries가 첫 호출 이후 영구히 재사용되므로, dev 서버가 장시간 떠 있는 상태에서 컴포넌트 MDX를 추가/수정/삭제해도 /llms/docs/components.txt 결과에 반영되지 않습니다. 빌드 타임에만 실행된다면 문제없지만, HMR/런타임 호출 경로가 있다면 NODE_ENV !== 'production'에서 캐시를 우회하거나 파일 mtime 기반 무효화를 고려해 주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 86 - 91, The
module-level cache (cachedEntries) never invalidates, so getEntries() will
return stale ComponentEntry[] after files change; update getEntries() to
invalidate or bypass the cache when NODE_ENV !== 'production' (or when file
mtimes change): e.g., check process.env.NODE_ENV and call loadEntries() directly
in dev, or track last-modified timestamps of the source MDX files and refresh
cachedEntries when any mtime is newer; target symbols: cachedEntries,
getEntries, and loadEntries.

50-52: titleCase는 첫 글자만 대문자화합니다.

(form-controls) 같은 다단어/하이픈 카테고리 폴더가 생기면 "Form-controls"처럼 어색하게 출력됩니다. 현재 카테고리 폴더 네이밍 컨벤션이 단일 소문자 단어로 고정되어 있다면 문제 없지만, 향후 확장을 고려해 단어 경계별 대문자화(또는 하이픈/언더스코어 처리)를 권장합니다.

♻️ 예시
-function titleCase(value: string): string {
-  return value.charAt(0).toUpperCase() + value.slice(1);
-}
+function titleCase(value: string): string {
+  return value
+    .split(/[-_\s]+/)
+    .filter(Boolean)
+    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
+    .join(" ");
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 50 - 52, titleCase
currently only uppercases the first character and yields awkward results for
multi-word or hyphenated names; update the titleCase function to split the input
on hyphens, underscores or spaces (e.g. using a regex like /[-_\s]+/),
capitalize the first letter of each segment and lowercase the rest, then join
the segments with a space so inputs like "form-controls" or "multi_word name"
become "Form Controls" (handle empty segments safely).

108-111: description 내 특수문자로 마크다운이 깨질 수 있습니다.

프론트매터 description], ), 개행, 백틱 등이 포함되면 - [title](url) — description 라인이 깨집니다. 프론트매터 파싱 단계에서 따옴표는 이미 벗겨지므로, 렌더 시점에 최소한 ]/)/개행 정도는 이스케이프하거나 치환하는 것을 권장합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 108 - 111,
description에 포함된 특수문자 때문에 마크다운이 깨집니다; for (const entry of list) 루프에서 suffix를 만들기
전에 entry.description을 안전하게 치환/이스케이프하세요 (예: ']' → '\]', ')' → '\)', 줄바꿈은 공백 또는
'\\n'으로 대체, 백틱은 '\`'로 이스케이프 등). 그런 다음 lines.push(`-
[${entry.title}](${entry.url})${suffix}`)에서 치환된 safeDescription을 사용하도록 변경하세요.

33-48: parseFrontmatter 유틸리티는 프론트매터 파싱 개선으로 이점을 볼 수 있습니다.

현재 정규식 /^["']|["']$/g는 비대칭 입력(예: title: 'Hello")을 예기치 않게 처리하며, 프로젝트에 이미 있는 yaml@^2.8.2 라이브러리를 사용하면 더 견고하게 만들 수 있습니다. 실제 문서의 프론트매터는 따옴표 없는 단순 key-value 형식(title: Docs MCP, description: ...)이므로 현재 동작에 즉각적인 문제는 없지만, 더 견고한 파싱을 위해 yaml 패키지 활용을 검토할 수 있습니다.

참고로, componentGridRule의 Rule 인터페이스 구현(이름, match, transform)은 적절하게 분리되어 있고, 에러 처리도 안전하게 원본 노드를 반환하고 있습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 33 - 48, Replace
the fragile manual frontmatter parsing in parseFrontmatter with the project's
yaml library: keep the existing frontmatter extraction (the regex that finds the
--- block) but pass match[1] to YAML.parse (imported from the yaml@^2.8.2
package) to obtain a parsed object, then convert/normalize its values to strings
(e.g., String(value)) before returning a Record<string,string>; catch and return
{} on parse errors so behavior remains safe. Ensure you update the
parseFrontmatter function to import YAML and to handle non-string YAML values
and exceptions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 86-91: The module-level cache (cachedEntries) never invalidates,
so getEntries() will return stale ComponentEntry[] after files change; update
getEntries() to invalidate or bypass the cache when NODE_ENV !== 'production'
(or when file mtimes change): e.g., check process.env.NODE_ENV and call
loadEntries() directly in dev, or track last-modified timestamps of the source
MDX files and refresh cachedEntries when any mtime is newer; target symbols:
cachedEntries, getEntries, and loadEntries.
- Around line 50-52: titleCase currently only uppercases the first character and
yields awkward results for multi-word or hyphenated names; update the titleCase
function to split the input on hyphens, underscores or spaces (e.g. using a
regex like /[-_\s]+/), capitalize the first letter of each segment and lowercase
the rest, then join the segments with a space so inputs like "form-controls" or
"multi_word name" become "Form Controls" (handle empty segments safely).
- Around line 108-111: description에 포함된 특수문자 때문에 마크다운이 깨집니다; for (const entry of
list) 루프에서 suffix를 만들기 전에 entry.description을 안전하게 치환/이스케이프하세요 (예: ']' → '\]',
')' → '\)', 줄바꿈은 공백 또는 '\\n'으로 대체, 백틱은 '\`'로 이스케이프 등). 그런 다음 lines.push(`-
[${entry.title}](${entry.url})${suffix}`)에서 치환된 safeDescription을 사용하도록 변경하세요.
- Around line 33-48: Replace the fragile manual frontmatter parsing in
parseFrontmatter with the project's yaml library: keep the existing frontmatter
extraction (the regex that finds the --- block) but pass match[1] to YAML.parse
(imported from the yaml@^2.8.2 package) to obtain a parsed object, then
convert/normalize its values to strings (e.g., String(value)) before returning a
Record<string,string>; catch and return {} on parse errors so behavior remains
safe. Ensure you update the parseFrontmatter function to import YAML and to
handle non-string YAML values and exceptions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 63621421-39bf-49d6-b860-49914712fd80

📥 Commits

Reviewing files that changed from the base of the PR and between 6ed8858 and 8035644.

📒 Files selected for processing (5)
  • docs/app/_llms/__fixtures__/component-grid/basic.output.md
  • docs/app/_llms/__fixtures__/component-grid/passthrough.input.mdx
  • docs/app/_llms/__fixtures__/component-grid/passthrough.output.mdx
  • docs/app/_llms/rules/component-grid-rule.test.ts
  • docs/app/_llms/rules/component-grid-rule.ts
✅ Files skipped from review due to trivial changes (3)
  • docs/app/_llms/fixtures/component-grid/passthrough.output.mdx
  • docs/app/_llms/fixtures/component-grid/passthrough.input.mdx
  • docs/app/_llms/fixtures/component-grid/basic.output.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/app/_llms/rules/component-grid-rule.test.ts

Replace hardcoded /llms/docs/components/{slug}.txt template with the
existing getLLMMarkdownUrl helper so URL construction stays centralized.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
docs/app/_llms/rules/component-grid-rule.ts (1)

16-21: ⚠️ Potential issue | 🟡 Minor

deprecated 판정은 true 계열 allowlist로 좁히는 편이 안전합니다.

현재는 빈 값/false/no만 제외해서 deprecated: offdeprecated: 0 같은 false 계열 값도 deprecated로 처리되어 컴포넌트 인덱스에서 빠질 수 있습니다. 명시적인 true 계열만 제외하도록 좁혀 주세요.

🐛 제안 수정
 export function isDeprecatedValue(value: string | undefined): boolean {
   if (value === undefined) return false;
   const normalized = value.trim().toLowerCase();
   if (normalized === "") return false;
-  return normalized !== "false" && normalized !== "no";
+  return normalized === "true" || normalized === "yes" || normalized === "on" || normalized === "1";
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 16 - 21, The
isDeprecatedValue function currently treats any value other than
empty/"false"/"no" as deprecated, which mislabels values like "off" or "0";
update isDeprecatedValue to return true only for an explicit true allowlist
(e.g., "true","yes","1","on") and false for all other values (still returning
false for undefined/empty). Modify the logic inside isDeprecatedValue to
normalize the input and check membership in that explicit true-set instead of
using the current negative checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 16-21: The isDeprecatedValue function currently treats any value
other than empty/"false"/"no" as deprecated, which mislabels values like "off"
or "0"; update isDeprecatedValue to return true only for an explicit true
allowlist (e.g., "true","yes","1","on") and false for all other values (still
returning false for undefined/empty). Modify the logic inside isDeprecatedValue
to normalize the input and check membership in that explicit true-set instead of
using the current negative checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff14e8c9-dadf-42fa-924b-5b15a4344355

📥 Commits

Reviewing files that changed from the base of the PR and between 8035644 and cbab001.

📒 Files selected for processing (1)
  • docs/app/_llms/rules/component-grid-rule.ts

@SeieunYoo SeieunYoo requested review from junghyeonsu and te6-in April 23, 2026 09:21
return null;
}

function parseFrontmatter(source: string): Record<string, string> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

언젠가는 gray-matter로 다 갈아 버리시죠..!

SeieunYoo and others added 2 commits April 23, 2026 21:27
Replace the ad-hoc regex parser and string-based isDeprecatedValue
helper with gray-matter, consistent with generate-docs-index. Boolean
frontmatter values are now parsed as real booleans.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
docs/app/_llms/rules/component-grid-rule.ts (2)

70-75: 프로세스 수명 동안 유지되는 캐시로 인한 개발 중 stale 위험.

cachedEntries는 모듈 수준에서 한 번만 채워지고 무효화 수단이 없습니다. 빌드 타임 일회성 실행에서는 문제가 없지만, 같은 프로세스에서 dev 서버가 장시간 유지되는 경우 새로 추가/수정한 컴포넌트 MDX가 반영되지 않습니다. Rule 인터페이스에 reset 훅이 없는 점을 감안할 때, 최소한 NODE_ENV !== "production"일 때는 캐시를 건너뛰는 것을 고려해 보세요.

♻️ 제안 수정
 function getEntries(): ComponentEntry[] {
+  if (process.env.NODE_ENV !== "production") return loadEntries();
   if (cachedEntries === null) cachedEntries = loadEntries();
   return cachedEntries;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 70 - 75, The
module-level cachedEntries causes stale data in long-lived dev processes; update
getEntries to bypass or not persist the cache when not in production by checking
process.env.NODE_ENV !== "production" and, in that case, always call
loadEntries() (or return a fresh load) instead of returning cachedEntries; keep
using cachedEntries only when NODE_ENV === "production" so loadEntries() is
still cached in production. Ensure you reference and modify cachedEntries,
getEntries, and loadEntries accordingly.

34-36: titleCase가 다중 단어 카테고리를 제대로 처리하지 못합니다.

(data-display)(form-controls) 같은 하이픈/언더스코어 카테고리 폴더명이 오면 Data-display처럼 첫 글자만 대문자가 되어 결과물 가독성이 떨어집니다. 단어 구분자 단위로 타이틀 케이스를 적용하는 방식을 고려해 주세요.

♻️ 제안 수정
 function titleCase(value: string): string {
-  return value.charAt(0).toUpperCase() + value.slice(1);
+  return value
+    .split(/[-_\s]+/)
+    .map((w) => (w ? w.charAt(0).toUpperCase() + w.slice(1) : w))
+    .join(" ");
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 34 - 36, titleCase
함수가 하이픈/언더스코어가 포함된 다중 단어 카테고리를 제대로 처리하지 못하므로, titleCase 구현을 변경해 단어
구분자(/[-_\s]+/)로 문자열을 분리한 뒤 각 토큰의 첫 글자만 대문자로 나머지는 소문자로 변환하고 공백으로 연결하여 반환하도록
수정하세요; 대상 심볼: function titleCase(value: string): string, 업데이트 시 입력에 빈값이 들어올 경우
기존 동작(빈 문자열 반환)을 유지하도록 처리하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 23-32: resolveComponentsDir currently returns null silently which
causes loadEntries to return an empty array and transform to leave the original
<ComponentGrid /> node unchanged; add a visible warning when the components
directory cannot be found so CI/builds can catch it. Specifically, update
resolveComponentsDir (or immediately after its return in loadEntries) to emit a
warning via the project's logging facility (e.g., processLogger.warn or
console.warn if no logger is available) that includes the attempted candidate
paths and the fact that component entries were not loaded; ensure the warning is
produced before transform runs so the missing directory is recorded during CI.

---

Nitpick comments:
In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 70-75: The module-level cachedEntries causes stale data in
long-lived dev processes; update getEntries to bypass or not persist the cache
when not in production by checking process.env.NODE_ENV !== "production" and, in
that case, always call loadEntries() (or return a fresh load) instead of
returning cachedEntries; keep using cachedEntries only when NODE_ENV ===
"production" so loadEntries() is still cached in production. Ensure you
reference and modify cachedEntries, getEntries, and loadEntries accordingly.
- Around line 34-36: titleCase 함수가 하이픈/언더스코어가 포함된 다중 단어 카테고리를 제대로 처리하지 못하므로,
titleCase 구현을 변경해 단어 구분자(/[-_\s]+/)로 문자열을 분리한 뒤 각 토큰의 첫 글자만 대문자로 나머지는 소문자로 변환하고
공백으로 연결하여 반환하도록 수정하세요; 대상 심볼: function titleCase(value: string): string, 업데이트 시
입력에 빈값이 들어올 경우 기존 동작(빈 문자열 반환)을 유지하도록 처리하세요.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fa5d33b9-8c03-452d-b048-427f55dfd6f3

📥 Commits

Reviewing files that changed from the base of the PR and between cbab001 and 0cb61b8.

📒 Files selected for processing (3)
  • docs/app/_llms/rules/component-grid-rule.test.ts
  • docs/app/_llms/rules/component-grid-rule.ts
  • docs/app/_llms/rules/index.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/app/_llms/rules/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/app/_llms/rules/component-grid-rule.test.ts

Comment thread docs/app/_llms/rules/component-grid-rule.ts
Silently returning null masked the original symptom this PR fixes —
the <ComponentGrid /> MDX tag leaking into llms.txt output. Log the
attempted candidate paths so CI/builds can surface the failure.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
docs/app/_llms/rules/component-grid-rule.ts (3)

52-55: 디렉터리 엔트리를 파일로 오인할 수 있습니다.

fs.readdirSync(categoryDir)는 파일/디렉터리 구분 없이 이름 목록을 반환합니다. 카테고리 하위에 .mdx로 끝나는 디렉터리가 우연히 존재하면 Line 55의 fs.readFileSyncEISDIR을 던지고, 바깥 transformcatch로 전파되어 전체 컴포넌트 그리드가 조용히 원본 MDX 노드로 폴백됩니다. 현재 구조상 발생 가능성은 낮지만, 상위 readdirSync와 동일하게 withFileTypes로 필터링하는 편이 일관성·안전성 면에서 낫습니다.

♻️ 제안 수정
-    for (const file of fs.readdirSync(categoryDir)) {
-      if (!file.endsWith(".mdx")) continue;
+    for (const entry of fs.readdirSync(categoryDir, { withFileTypes: true })) {
+      if (!entry.isFile() || !entry.name.endsWith(".mdx")) continue;
+      const file = entry.name;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 52 - 55, The code
treats entries from fs.readdirSync(categoryDir) as files and may call
fs.readFileSync on directories; change the loop that iterates categoryDir
entries (in component-grid-rule.ts) to call fs.readdirSync(categoryDir, {
withFileTypes: true }) and filter Dirent objects by dirent.isFile() &&
dirent.name.endsWith('.mdx') before calling fs.readFileSync on
path.join(categoryDir, dirent.name); this mirrors the earlier use of
withFileTypes and prevents EISDIR when a directory name ends with .mdx.

71-76: 모듈 수준 캐시가 영구히 유지됩니다.

cachedEntries는 프로세스 수명 동안 무효화되지 않습니다. 빌드 시점 1회 실행이라면 무해하지만, next dev나 watch 환경에서 동일 프로세스가 재사용되는 경우 새로 추가/삭제된 컴포넌트 문서가 반영되지 않습니다. 파일 시스템 변경이 빈번한 개발 환경을 지원해야 한다면 mtime 기반 재검증이나 개발 모드에서만 캐시를 비활성화하는 방안을 고려해 주세요. (현재 사용 맥락이 빌드 전용이라면 무시하셔도 됩니다.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 71 - 76, The
module-level cache cachedEntries (used by getEntries and populated via
loadEntries) is never invalidated, so additions/deletions during a long-lived
process (eg. next dev/watch) won't be picked up; change getEntries to either
skip caching in development (check NODE_ENV or a dev flag) or add revalidation
logic (compare directory/file mtimes or a timestamp and call loadEntries again
when sources changed) so loadEntries is re-run when filesystem changes are
detected; ensure cachedEntries is updated/cleared after revalidation.

110-110: html 노드로 Markdown 문자열을 주입하는 방식 재고.

현재 buildMarkdown()이 생성한 Markdown 문자열(## …, - […](url))을 type: "html" 노드로 삽입합니다. 최종 직렬화기가 mdast-util-to-markdown이면 html 노드는 그대로 통과되어 결과물에서는 Markdown으로 보이지만, 의미상으론 AST가 HTML로 태그되어 있어 downstream에서 heading/list 노드를 순회하는 다른 룰/플러그인이 이 섹션을 건너뛰게 됩니다. 가능하다면 heading/list/listItem/link/text 등 mdast 노드를 직접 조립해 반환하는 편이 파이프라인 확장성에 유리합니다.

As per coding guidelines: "Prioritize AST transformation over string regex post-processing".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` at line 110, The code currently
injects a Markdown string via a node like `return [{ type: "html", value:
buildMarkdown(entries) }];` which treats the content as HTML and breaks
downstream AST traversal; instead modify the implementation so you assemble and
return mdast nodes directly (e.g., create `heading`, `list`, `listItem`, `link`,
`text` nodes) rather than a single `html` node. Update `buildMarkdown` (or
create a new helper called by the rule) to output an array of mdast node objects
(heading/list/listItem/link/text) and change the return to return that array of
nodes so other rules/plugins can traverse semantic AST nodes. Ensure node shapes
follow mdast conventions (type and children/position/identifier where
applicable).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 106-114: The transform() catch block currently swallows errors
from getEntries()/buildMarkdown() silently; change it to catch the thrown error
(catch (err)) and emit a warning log containing context ("ComponentGrid
transform failed" or similar) plus the error details before returning [node],
using the project's existing logger (e.g., processLogger.warn) or console.warn
if no logger is in scope; keep the safe fallback to return the original node but
ensure CI/builds can detect the problem via the logged warning.

---

Nitpick comments:
In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 52-55: The code treats entries from fs.readdirSync(categoryDir) as
files and may call fs.readFileSync on directories; change the loop that iterates
categoryDir entries (in component-grid-rule.ts) to call
fs.readdirSync(categoryDir, { withFileTypes: true }) and filter Dirent objects
by dirent.isFile() && dirent.name.endsWith('.mdx') before calling
fs.readFileSync on path.join(categoryDir, dirent.name); this mirrors the earlier
use of withFileTypes and prevents EISDIR when a directory name ends with .mdx.
- Around line 71-76: The module-level cache cachedEntries (used by getEntries
and populated via loadEntries) is never invalidated, so additions/deletions
during a long-lived process (eg. next dev/watch) won't be picked up; change
getEntries to either skip caching in development (check NODE_ENV or a dev flag)
or add revalidation logic (compare directory/file mtimes or a timestamp and call
loadEntries again when sources changed) so loadEntries is re-run when filesystem
changes are detected; ensure cachedEntries is updated/cleared after
revalidation.
- Line 110: The code currently injects a Markdown string via a node like `return
[{ type: "html", value: buildMarkdown(entries) }];` which treats the content as
HTML and breaks downstream AST traversal; instead modify the implementation so
you assemble and return mdast nodes directly (e.g., create `heading`, `list`,
`listItem`, `link`, `text` nodes) rather than a single `html` node. Update
`buildMarkdown` (or create a new helper called by the rule) to output an array
of mdast node objects (heading/list/listItem/link/text) and change the return to
return that array of nodes so other rules/plugins can traverse semantic AST
nodes. Ensure node shapes follow mdast conventions (type and
children/position/identifier where applicable).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aa8bc0e1-bcdf-4e31-8493-a793590d77fb

📥 Commits

Reviewing files that changed from the base of the PR and between 0cb61b8 and 10f2b41.

📒 Files selected for processing (1)
  • docs/app/_llms/rules/component-grid-rule.ts

Comment thread docs/app/_llms/rules/component-grid-rule.ts
Mirror the resolveComponentsDir warning: surfacing the fallback so a
failing getEntries/buildMarkdown can be caught in CI instead of
silently leaving the <ComponentGrid /> tag in llms.txt output.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants